package com.zxtech.zzm.zxmonitorsocket.resolver

import android.content.Intent
import com.zxtech.zzm.core.util.CodecUtil
import com.zxtech.zzm.core.util.DeviceUtil
import com.zxtech.zzm.core.util.HexUtil
import com.zxtech.zzm.core.util.RootUtil
import com.zxtech.zzm.shell.ShellUtils
import com.zxtech.zzm.zxmonitorsocket.SocketPackage
import com.zxtech.zzm.zxmonitorsocket.SocketPackageSend
import com.zxtech.zzm.zxmonitorsocket.ZXMonitorSocketService
import com.zxtech.zzm.zxmonitorsocket.util.SocketLoggerUtil
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset

class ShellResolver : SocketBaseResolver() {
  private val SHELL_PREFIX = "export LD_LIBRARY_PATH=./lib:\$LD_LIBRARY_PATH && "
  override fun resolve(content: Any) {
    val socketPackage: SocketPackage = content as SocketPackage
    val userUUID: String = socketPackage.packageContent!!.substring(2, 34) //用户UUID
    var shellCMD: String? = null
    try {
      shellCMD = String(
        HexUtil.decodeHex(
          socketPackage.packageContent!!.substring(34)
            .toCharArray()
        ), Charset.forName("UTF-8")
      )
    } catch (e: UnsupportedEncodingException) {
      e.printStackTrace()
    }
    SocketLoggerUtil.logSocket("shellCMD = $shellCMD")
    if ("reboot" == shellCMD) { //Shell命令重启ZXTablet应用
      ZXMonitorSocketService.context!!
        .sendBroadcast(Intent("com.zxtech.zzm.zxmonitor.REBOOT_ZXTABLET_BROADCAST"))
    }
    if (RootUtil.isDeviceRooted) {
      shellCMD = SHELL_PREFIX + shellCMD
    }
    var result: String = ShellUtils.execCommand(shellCMD, RootUtil.isDeviceRooted)
      .toString()
    //String result = "shellCMD in new way " + ShellUtils.execCommand(shellCMD.split(" "));
    do {
      val result_part = result.substring(0, if (result.length > 1000) 1000 else result.length)
      SocketLoggerUtil.logSocket("result_part = $result_part")
      result = result.substring(if (result.length > 1000) 1000 else result.length)
      val result_bytes = result_part.toByteArray()
      val length = (result_bytes.size + 18).toShort()
      val lengthByte: ByteArray = CodecUtil.short2bytes(length)
      val data_bytes = ByteArray(length + 18)
      data_bytes[0] = 0x00
      data_bytes[17] = 0x01
      val userUUIDbytes: ByteArray = CodecUtil.hexStringToByte(userUUID)
      System.arraycopy(userUUIDbytes, 0, data_bytes, 1, userUUIDbytes.size)
      System.arraycopy(result_bytes, 0, data_bytes, 18, result_bytes.size)
      val builder = SocketPackageSend.Builder()
      builder.setPackageLength(byteArrayOf(lengthByte[0], lengthByte[1]))
        .setType(0x23.toByte())
        .setIdBytes(
          DeviceUtil.getTerminalID()
            .toByteArray()
        )
        .setData(data_bytes)
      ZXMonitorSocketService.sendPackage(builder)
    } while (result.isNotEmpty())
  }

  private fun runShell(shellCMD: String): String {
    var deviceInfo = ""
    try {
      val p = Runtime.getRuntime()
        .exec(shellCMD)
      val `in` = BufferedReader(InputStreamReader(p.inputStream))
      var line: String? = null
      while (`in`.readLine()
          .also { line = it } != null
      ) {
        deviceInfo += line!!.trim { it <= ' ' }
      }
    } catch (e: Exception) {
      e.printStackTrace()
    }
    return deviceInfo
  }

  companion object {
    private val instance = ShellResolver()
    fun handlePackage(socketPackage: SocketPackage?) {
      instance.resolve(socketPackage!!)
    }
  }
}